/*
 * Copyright 2008 Mark Davidson.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.doofer.test

import org.doofer.*
import com.documentum.com.*
import com.documentum.fc.common.*
import com.documentum.fc.client.*

/**
 * Bootstrap tests
 */
class BootstrapTest extends DooferBaseTest {

    def su = null
    def qu = null
    def ou = null

    void setUp() {
        super.setUp()
        new Bootstrap().boot()
        su = new SessionUtil(username: username, password: password, repository: repository)
        qu = new QueryUtil()
        ou = new ObjectUtil()
    }

    void testGetObjectUsingMap() {
        println "testing IDfSession.getObject() using map"
        su.useSession { session ->
            def cabinetName = 'Templates'
            def path = "/$cabinetName"
            def qual = "dm_cabinet where object_name = '$cabinetName'"
            def cabinet = null

            cabinet = session.getObject(path: path)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.getString('object_name'))
            def objectId = cabinet.objectId.id

            cabinet = session.getObject(objectId: objectId)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.getString('object_name'))

            cabinet = session.getObject(qualification: qual)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.getString('object_name'))
        }
    }

    void testGetObjectById() {
        println "testing IDfSession.getObject() by id"
        def cabinetName = 'Templates'
        su.useSession { session ->
            def objectId = session.getObjectByPath("/$cabinetName").objectId.id
            def cabinet = session.getObject(objectId)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.getString('object_name'))
        }
    }

    void testGetSysObject() {
        println "testing IDfSession.getSysObject()"
        su.useSession { session ->
            def cabinet = null
            def objectId = null
            def cabinetName = 'Templates'
            def path = "/$cabinetName"
            def qual = "dm_cabinet where object_name = '$cabinetName'"

            cabinet = session.getSysObjectByPath("/$cabinetName")
            assert(cabinet)
            assertEquals(cabinetName, cabinet.objectName)
            objectId = cabinet.objectId.id

            cabinet = session.getSysObjectByQualification(qual)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.objectName)

            cabinet = session.getSysObject(new DfId(objectId))
            assert(cabinet)
            assertEquals(cabinetName, cabinet.objectName)

            cabinet = session.getSysObject(objectId)
            assert(cabinet)
            assertEquals(cabinetName, cabinet.objectName)
        }
    }

    void testGetDocument() {
        println "testing IDfSession.getDocument()"
        su.useSession { session ->
            def doc = null
            def objectId = null
            def folderPath = '/Templates'
            def docName = 'Blank PDF Document'
            def docPath = "$folderPath/$docName"
            def qual = "dm_document where object_name = '$docName' and folder('$folderPath')"

            doc = session.getDocumentByPath(docPath)
            assert(doc)
            assertEquals(docName, doc.objectName)
            objectId = doc.objectId.id

            doc = session.getDocumentByQualification(qual)
            assert(doc)
            assertEquals(docName, doc.objectName)

            doc = session.getDocument(new DfId(objectId))
            assert(doc)
            assertEquals(docName, doc.objectName)

            doc = session.getDocument(objectId)
            assert(doc)
            assertEquals(docName, doc.objectName)
        }
    }

    void testGetAt() {
        println "testing IDfTypedObject.getAt()"
        def objectName = 'Templates'
        def objectType = 'dm_cabinet'
        def dql = "select object_name, r_object_type from dm_cabinet where object_name = 'Templates'"
        def qu = new QueryUtil()
        su.useSession { session ->
            qu.execute(session: session, dql: dql) { row ->
                assertEquals(objectName, row[0])
                assertEquals(objectType, row[1])
                assertNull(row[2])
            }
        }
    }

    void testSize() {
        println "testing IDfTypedObject.size()"
        def dql1 = "select object_name from dm_cabinet where object_name = 'Templates'"
        def dql2 = "select object_name, r_object_id from dm_cabinet where object_name = 'Templates'"
        def qu = new QueryUtil()
        su.useSession { session ->
            qu.execute(session: session, dql: dql1) { row ->
                assertEquals(1, row.size())
            }
            qu.execute(session: session, dql: dql2) { row ->
                assertEquals(2, row.size())
            }
        }
    }

    void testPropertyMissingRead() {
        println "testing IDfTypedObject.propertyMissing() for read"
        def cabinetName = 'Templates'
        su.useSession() { session ->
            def cabinet = session.getObjectByPath("/$cabinetName")
            assert(cabinet)
            assertEquals(cabinetName, cabinet.object_name)
            assertEquals(cabinet.getId('i_chronicle_id').id, cabinet.i_chronicle_id)
        }
    }

    void testGetMap() {
        println "testing IDfTypedObject.getMap()"
        def results = []
        def dql =
        """
        select object_name, r_object_id
        from dm_cabinet
        where object_name in ('System','Templates')
        order by object_name, r_object_id
        """

        su.useSession { session ->
            qu.execute(session: session, dql: dql) { row ->
                def map = row.map
                assert(map)
                assertEquals(2, map.size())
                results << map
            }
        }

        assert(results)
        assertEquals(2, results.size())
    }

    void testPropertyMissingWrite() {
        println "testing IDfPersistentObject.propertyMissing() for write"
        def cabinetName = 'Templates'
        def newTitle = 'Renamed cabinet title'
        su.useSession { session ->
            def cabinet = session.getObjectByPath("/$cabinetName")
            assert(cabinet)
            cabinet.title = newTitle
            assertEquals(newTitle, cabinet.getString('title'))
        }
    }

    void testLeftShift() {
        println "testing IDfPersistentObject.leftShift()"
        def docName = 'Blank PDF Document'
        def newDocName = 'Renamed PDF Template'
        def newAuthors = ['Ren', 'Stimpy']
        def path = "/Templates/$docName"
        su.useSession { session ->
            def doc = session.getObjectByPath(path) as IDfDocument
            assert(doc)
            doc << [object_name: newDocName, authors: newAuthors]
            assertEquals(newDocName, doc.objectName)
            assertEquals(newAuthors, doc.getAllRepeatingStrings('authors', ',').split(','))
        }
    }

    void testSetAttribs() {
        println "testing IDfPersistentObject.setAttribs()"
        def docName = 'Blank PDF Document'
        def newDocName = 'Renamed PDF Template'
        def newAuthors = ['Ren', 'Stimpy']
        def path = "/Templates/$docName"
        su.useSession { session ->
            def doc = session.getObjectByPath(path) as IDfDocument
            assert(doc)
            doc.setAttribs(object_name: newDocName, authors: newAuthors)
            assertEquals(newDocName, doc.objectName)
            assertEquals(newAuthors, doc.getAllRepeatingStrings('authors', ',').split(','))
        }
    }

    void testGetText() {
        println "testing IDfPersistentObject.getText()"
        su.useSession { session ->
            def text = null
            def pathToIniFile = "/Templates/MenuSystemTemplate.ini"
            def object = session.getObjectByPath(pathToIniFile)
            assert(object)

            text = object.text
            assert(text)
            text = object.getText(format: 'crtext', pageNum: 0)
            assert(text)
            text = object.getText(format: 'crtext')
            assert(text)
        }
    }

    void testToFile() {
        println "testing IDfPersistentObject.toFile()"
        su.useSession { session ->
            def pathToIniFile = "/Templates/MenuSystemTemplate.ini"
            def object = session.getObjectByPath(pathToIniFile)
            assert(object)

            def target = 'test.txt'
            def file = object.toFile(target: target)
            assert(file)
            assert(file.exists())
            if(file.exists()) file.delete()
        }
    }

    void testGetContent() {
        println "testing IDfPersistentObject.getContent()"
        su.useSession { session ->
            def pathToIniFile = "/Templates/MenuSystemTemplate.ini"
            def object = session.getObjectByPath(pathToIniFile)
            assert(object)

            def bais = object.getContent(format: 'crtext', pageNum: 0)
            assert(bais)
        }
    }

    void testQuery() {
        println "testing IDfSession.query()"
        su.useSession { session ->
            def cabinetNames = []
            def dql = "select object_name from dm_cabinet where object_name in ('System','Templates') order by object_name"
            session.query(dql: dql) { row ->
                cabinetNames << row.getString('object_name')
            }
            assert(cabinetNames)
            assertEquals(2, cabinetNames.size())
            assertEquals('System', cabinetNames[0])
            assertEquals('Templates', cabinetNames[1])
        }
    }

    void testQueryForList() {
        println "testing IDfSession.queryForList()"
        su.useSession { session ->
            def results = null
            def dql = "select object_name from dm_cabinet where object_name in ('System','Templates') order by object_name"

            results = session.queryForList(dql: dql)
            assert(results)
            assert(true)
            assertEquals(2, results.size())
            assertEquals('System', results[0].object_name)
            assertEquals('Templates', results[1].object_name)

            def pos = 0
            results = session.queryForList(dql: dql) { row ->
                row.pos = ++pos
            }
            assert(results)
            assert(true)
            assertEquals(2, results.size())
            assertEquals('System', results[0].object_name)
            assertEquals('Templates', results[1].object_name)
            assertEquals(1, results[0].pos)
            assertEquals(2, results[1].pos)
        }
    }

    void testWalkObjects() {
        println "testing IDfSession.walkObjects()"

        def containers = ['AcsConfig', 'Applications', 'DataDictionary', 'Methods', 'Modules', 'TBO', 'SBO']
        def objects = ['MenuSystem.ini', 'FormatPreferences.ini']
        def failed = false
        def matchedContainers = []
        def matchedObjects = []

        try {
            su.useSession { session ->
                session.walkObjects(path: '/System', recursive: true) { object ->
                    if(containers.contains(object.objectName)) matchedContainers << object.objectName
                    else if(objects.contains(object.objectName)) matchedObjects << object.objectName
                }
            }
        } catch(Throwable t) {
            println "Detected error: $t.message"
            failed = true
        }

        assertFalse(failed)
        println "matchedContainers = $matchedContainers"
        println "matchedObjects = $matchedObjects"
        assertEquals(containers.size(), matchedContainers.size())
        //println "objects = ${objects.size()}"
        //println "matched = ${matchedObjects.size()}"
        assertEquals(objects.size(), matchedObjects.size())
    }

    void testDeltree() {
        println "testing IDfSession.deltree()"
        su.useSession() { session ->
            def doc = ou.createObject(session: session, objectType: 'dm_document', objectName: 'test', link: "/$username/doofer/subfolder")
            if(doc) {
                session.deltree(path: "/$username/doofer")
                assertNull(session.getObjectByPath("/$username/doofer/subfolder/test"))
                assertNull(session.getObjectByPath("/$username/doofer/subfolder"))
                session.getObjectByPath("/$username/doofer").destroy()
                assertNull(session.getObjectByPath("/$username/doofer"))
            }
        }
    }

    void testImportDocument() {
        println "testing IDfSession.importDocument()"
        def failed = false

        try {
            su.useSession { session ->
                def sourcePath = 'samples/data/OSS/The Cathedral And The Bazaar.pdf'
                def targetPath = "/$username"
                def objectType = 'dm_document'
                def title = 'The Cathedral And The Bazaar'
                def params = [sourcePath: sourcePath, targetPath: targetPath, objectType: objectType]

                session.importDocument(params) { it.title = title }
                def doc = session.getObjectByPath("$targetPath/$title")
                assert(doc)
                assertEquals(title, doc.objectName)
                assertEquals(title, doc.title)
                assertEquals(objectType, doc.typeName)
                assertEquals('pdf', doc.contentType)
                doc.destroy()
                assert(true)
            }
        } catch(Throwable t) {
            println "Detected error: $t.message"
            failed = true
        }

        assertFalse(failed)
    }

    void testGetChildTypes() {
        println "testing IDfType.getChildTypes()"
        su.useSession { session ->
            def type = session.getType('dm_document')
            def subTypes = type.getChildTypes()
            assert(subTypes)
            assert(subTypes.contains('dm_menu_system'))
            assert(subTypes.contains('dm_xml_config'))
            assertFalse(subTypes.contains('dm_document'))
            assertFalse(subTypes.contains('dm_user'))
        }
    }

    void testHasChildType() {
        println "testing IDfType.hasChildType()"
        su.useSession { session ->
            def type = session.getType('dm_document')
            assertTrue(type.hasChildType('dm_menu_system'))
            assertTrue(type.hasChildType('dm_xml_config'))
            assertFalse(type.hasChildType('dm_document'))
            assertFalse(type.hasChildType('dm_user'))
        }
    }

    void testGetParentTypes() {
        println "testing IDfType.getParentTypes()"
        su.useSession { session ->
            def type = session.getType('dm_xml_config')
            def parentTypes = type.getParentTypes()
            assert(parentTypes)
            assert(parentTypes.contains('dm_document'))
            assert(parentTypes.contains('dm_sysobject'))
        }
    }

    void testHasParentType() {
        println "testing IDfType.hasParentType()"
        su.useSession { session ->
            def type = session.getType('dm_menu_system')
            assertTrue(type.hasParentType('dm_document'))
            assertTrue(type.hasParentType('dm_sysobject'))
            type = session.getType('dm_xml_config')
            assertTrue(type.hasParentType('dm_document'))
            type = session.getType('dm_user')
            assertFalse(type.hasParentType('dm_document'))
        }
    }

    void testGetDooferVersion() {
        println "testing getDooferVersion()"
        def clientX = new DfClientX()
        def version = clientX.dooferVersion
        assert(version)
        assertEquals('0.31', version)
    }
}